package com.itheima.stock.service.impl;

import com.google.common.collect.Lists;
import com.itheima.stock.config.StockInfoConfig;
import com.itheima.stock.mapper.StockBlockRtInfoMapper;
import com.itheima.stock.mapper.StockBusinessMapper;
import com.itheima.stock.mapper.StockMarketIndexInfoMapper;
import com.itheima.stock.mapper.StockRtInfoMapper;
import com.itheima.stock.pojo.StockBlockRtInfo;
import com.itheima.stock.pojo.StockMarketIndexInfo;
import com.itheima.stock.pojo.StockRtInfo;
import com.itheima.stock.service.StockTimerTaskService;
import com.itheima.stock.utils.DateTimeUtil;
import com.itheima.stock.utils.IdWorker;
import com.itheima.stock.utils.ParseType;
import com.itheima.stock.utils.ParserStockInfoUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @Author Polo
 * @Description //TODO
 * @Date 2022-05-14 23:19
 * @Version 1.0
 */
@Service("stockTimerTaskService")
@Slf4j
public class StockTimerTaskServiceImpl implements StockTimerTaskService {
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private StockInfoConfig stockInfoConfig;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private StockMarketIndexInfoMapper stockMarketIndexInfoMapper;
    @Autowired
    private StockBusinessMapper stockBusinessMapper;
    @Autowired
    private StockRtInfoMapper stockRtInfoMapper;
    @Autowired
    private ParserStockInfoUtil parserStockInfoUtil;
    @Override
    public void getInnerMarketInfo() {
        //定义采集的url接口
        String url = stockInfoConfig.getMarketUrl() + String.join(",", stockInfoConfig.getInner());
        //此连接有防盗链  所以需要对请求头进行一些处理
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Referer","https://finance.sina.com.cn/stock/");
        httpHeaders.add("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36");
        //开始组装restTemplate请求对象
        HttpEntity<Object> entity = new HttpEntity<>(httpHeaders);
        //发送并接受数据,也可以直接获取对象
        //restTemplate.postForObject(url,entity,String.class);
        ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
        String result = exchange.getBody();
        //设置正则分组规则
        String reg="var hq_str_(.*)=\"(.*)\";";
        //创建正则分组对象
        Pattern pattern = Pattern.compile(reg);
        //对接口url返回数据进行解析 并分组
        Matcher matcher = pattern.matcher(result);
        //提前准备集合用来装解析并封装好的对象
        ArrayList<StockMarketIndexInfo> list = new ArrayList<>();
        while (matcher.find()){
            //获取大盘编号
            String marketCode = matcher.group(1);
            //获取大盘所有数据
            String marketDates = matcher.group(2);
            //把大盘数据拆分为数组
            String[] splitArr = marketDates.split(",");
            //大盘名称
            String marketName=splitArr[0];
            //获取当前大盘的点数
            BigDecimal openPoint=new BigDecimal(splitArr[1]);
            //获取大盘的涨跌值
            BigDecimal preClosePoint=new BigDecimal(splitArr[2]);
            //获取大盘的涨幅
            BigDecimal curPoint=new BigDecimal(splitArr[3]);
            //获取大盘最高点
            BigDecimal maxPoint=new BigDecimal(splitArr[4]);
            //获取大盘的涨幅
            BigDecimal minPoint=new BigDecimal(splitArr[5]);
            //获取成交量
            Long tradeAmt=Long.valueOf(splitArr[8]);
            //获取成交金额
            BigDecimal tradeVol=new BigDecimal(splitArr[9]);
            //时间
            Date curTime = DateTimeUtil.getDateTimeWithoutSecond(splitArr[30] + " " + splitArr[31]).toDate();
            //组装成entity(pojo)对象 StockMarketIndexInfo该类已定义为建造者模式
            StockMarketIndexInfo info=StockMarketIndexInfo.builder()
                    .id(idWorker.nextId() + "")
                    .marketCode(marketCode)
                    .marketName(marketName)
                    .curPoint(curPoint)
                    .openPoint(openPoint)
                    .preClosePoint(preClosePoint)
                    .maxPoint(maxPoint)
                    .minPoint(minPoint)
                    .tradeVolume(tradeVol)
                    .tradeAmount(tradeAmt)
                    .curTime(curTime)
                    .build();
            //收集封装的对象  方便后期批量处理
            list.add(info);
            }
        log.info("采集当前大盘数据:{}",list);
        //批量插入前判断
        if (list.isEmpty()){
            return;
        }
        int count = stockMarketIndexInfoMapper.insertBatch(list);
        log.info("插入了{}条数据",count);
    }

    @Override
    public void getStockRtIndex() {
        //获取行业编码
        List<String> allBusinessCode = stockBusinessMapper.getAllBusinessCode();
        //计算出符合我们此次需要查询要求的编码
        List<String> codes = allBusinessCode.stream().map(id -> {
            return id.startsWith("6") ? "sh" + id : "sz" + id;
        }).collect(Collectors.toList());
        //接口有防盗链  设置一下header 然后创建httpEntity
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Referer","https://finance.sina.com.cn/stock/");
        httpHeaders.add("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36");
        HttpEntity<Object> entity = new HttpEntity<>(httpHeaders);
        //对行业编码集合分片处理
        Lists.partition(codes,15).forEach(code->{
            String url=stockInfoConfig.getMarketUrl()+String.join(",",code);
            //使用框架获取响应
            String result = restTemplate.postForObject(url, entity, String.class);
            List<StockRtInfo> infos = parserStockInfoUtil.parser4StockOrMarketInfo(result, ParseType.ASHARE);
            if (infos.isEmpty()){
                log.info("拉取数据失败!");
                return;
            }
            log.info("数据量：{}",infos.size());
            stockRtInfoMapper.insertBatch(infos);
        });

    }
}
